package jinyilw.swing;
import jinyilw.common.JvmTools;
import jinyilw.common.OSTools;
import jinyilw.common.ReflectTools;
import jinyilw.common.TextTools;

import java.awt.Component;
import java.awt.Desktop;
import java.awt.FileDialog;
import java.awt.Frame;
import java.awt.Image;
import java.awt.event.ActionListener;
import java.io.File;
import java.lang.reflect.Proxy;
public class NativeTools
{
	private static Object macApplication;
	private static Image macDockImage;
	private static Class<?> aboutHandleClass;
	private static Class<?> preferencesHandleClass;
	private static Class<?> quitHandleClass;
	private NativeTools()
	{
	}

	public static File chooseNativeFile(Component parent, String title,
			final String ext)
	{
		return getNativeFile(parent, title, FileDialog.LOAD, ext);
	}
	public static File getNativeSaveFile(Component parent, String title,
			final String ext)
	{
		return getNativeFile(parent, title, FileDialog.SAVE, ext);
	}
	public static File getNativeFile(Component parent, String title, int mode,
			String... exts)
	{
		FileDialog fileDialog = createNativeFileDialog(parent, title, mode,
				exts);
		// fileDialog.setResizable(true);
		fileDialog.setVisible(true);
		File[] files = fileDialog.getFiles();
		if (files != null && files.length > 0)
			return files[0];
		return null;
	}
	public static FileDialog createNativeFileDialog(Component parent,
			String title, int mode, final String... exts)
	{
		FileDialog fileDialog = new FileDialog(
				getFrame(parent), title, mode);
		if (exts.length > 0)
		{
			fileDialog.setFilenameFilter((dir, name) -> {
				String fileExt = TextTools.getFileExt(name);
				if (fileExt == null)
					return false;
				for (String ext : exts)
					if (fileExt.equalsIgnoreCase(ext))
						return true;
				return false;
			});
		}
		return fileDialog;
	}
	private static Frame getFrame(Component c)
	{
		for (Component p = c; p != null; p = p.getParent())
			if (p instanceof Frame)
				return (Frame) p;
		return null;
	}
	public static void setMacAppAboutName(String name)
	{
		if (OSTools.OSType.isMac)
		{
			System.setProperty(
					"com.apple.mrj.application.apple.menu.about.name", name);
		}
	}
	public static void setMacDockImage(Image image)
	{
		if (OSTools.OSType.isMac && image != macDockImage)
		{
			macDockImage = image;
			if (JvmTools.getJavaRuntimeVersion() < 17)
			{
				Object macApplication = getMacApplication();
				if (macApplication != null)
					ReflectTools.invokeMethod(macApplication.getClass(),
							macApplication, "setDockIconImage",
							new Class[]{Image.class}, image);
			}
		}
	}

	private static Object getMacApplication()
	{
		try
		{
			Class<?> macApplicationClass = Class
					.forName("com.apple.eawt.Application");
			return macApplicationClass.getMethod("getApplication").invoke(null);
		} catch (Exception e)
		{
			e.printStackTrace();
			return null;
		}
	}

	public static void enableMacAppMenuBar()
	{
		if (OSTools.OSType.isMac)
			System.setProperty("apple.laf.useScreenMenuBar", "true");
	}
	public static void setMacAboutListener(ActionListener listener)
	{
		setMacAppListener(listener, 1);
	}
	public static void setMacPreferencesListener(ActionListener listener)
	{
		setMacAppListener(listener, 2);
	}
	public static void setMacQuitListener(ActionListener listener)
	{
		setMacAppListener(listener, 3);
	}

	private static Object getDesktopOrApplication()
	{
		if (macApplication != null)
			return macApplication;
		if (JvmTools.getJavaRuntimeVersion() > 1.9)
			macApplication = Desktop.getDesktop();
		else
		{
			try
			{
				Class<?> cls = Class.forName("com.apple.eawt.Application");
				macApplication = cls.getMethod("getApplication").invoke(null);
			} catch (Exception ex)
			{
				throw new UnsupportedOperationException();
			}
		}
		return macApplication;
	}
	private static Class<?> initAboutHandleClass()
	{
		if (aboutHandleClass == null)
			try
			{
				if (JvmTools.getJavaRuntimeVersion() > 1.9)
					aboutHandleClass = Class
							.forName("java.awt.desktop.AboutHandler");
				else
					aboutHandleClass = Class
							.forName("com.apple.eawt.AboutHandler");
			} catch (ClassNotFoundException e)
			{
				aboutHandleClass = null;
				e.printStackTrace();
			}
		return aboutHandleClass;
	}
	private static Class<?> initPreferencesHandleClass()
	{
		if (preferencesHandleClass == null)
			try
			{
				if (JvmTools.getJavaRuntimeVersion() > 1.9)
					preferencesHandleClass = Class
							.forName("java.awt.desktop.PreferencesHandler");
				else
					preferencesHandleClass = Class
							.forName("com.apple.eawt.PreferencesHandler");
			} catch (ClassNotFoundException e)
			{
				preferencesHandleClass = null;
				e.printStackTrace();
			}
		return preferencesHandleClass;
	}
	private static Class<?> initQuitHandleClass()
	{
		if (quitHandleClass == null)
			try
			{
				if (JvmTools.getJavaRuntimeVersion() > 1.9)
					quitHandleClass = Class
							.forName("java.awt.desktop.QuitHandler");
				else
					quitHandleClass = Class
							.forName("com.apple.eawt.QuitHandler");
			} catch (ClassNotFoundException e)
			{
				quitHandleClass = null;
				e.printStackTrace();
			}
		return quitHandleClass;
	}
	private static void setMacAppListener(ActionListener listener, int type)
	{
		if (!OSTools.OSType.isMac || listener == null)
			return;
		Class<?> handleClass = null;
		String mName = null;
		switch (type)
		{
			case 1:
				handleClass = initAboutHandleClass();
				mName = "setAboutHandler";
				break;
			case 2:
				handleClass = initPreferencesHandleClass();
				mName = "setPreferencesHandler";
				break;
			case 3:
				handleClass = initQuitHandleClass();
				mName = "setQuitHandler";
		}
		if (handleClass == null)
			return;
		Object application = getDesktopOrApplication();
		Object mObj = Proxy.newProxyInstance(handleClass.getClassLoader(),
				new Class[]{handleClass}, (proxy, method, args) -> {
					listener.actionPerformed(null);
					return null;
				});
		ReflectTools.invokeMethod(application.getClass(), application, mName,
				new Class[]{handleClass}, mObj);
	}
	public static boolean isMacAppMenuBarEnabled()
	{
		return OSTools.OSType.isMac && Boolean.getBoolean("apple.laf.useScreenMenuBar");
	}
}
